package com.blue.Impl.job;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blue.common.constant.CommonConstant;
import com.blue.mapper.job.ScheduledJobMapper;
import com.blue.po.job.ScheduledJobPO;
import com.blue.service.job.IScheduledJobService;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


@Service
@Transactional
public class ScheduledJobServiceImpl extends ServiceImpl<ScheduledJobMapper, ScheduledJobPO> implements IScheduledJobService {

    @Autowired
    private Scheduler scheduler;

    /**
     * 立即执行的任务分组
     */
    private static final String JOB_EXECUTE_GROUP = "execute_group";

    @Override
    public void add(ScheduledJobPO scheduledJobPO) {
        //保存数据
        super.save(scheduledJobPO);
        if (CommonConstant.NORMAL.equals(scheduledJobPO.getJobStatus())) {
            // 添加定时器
            this.schedulerAdd(scheduledJobPO.getId(), scheduledJobPO.getClassName().trim(), scheduledJobPO.getCronExpression().trim(), scheduledJobPO.getParams());
        }
    }

    @Override
    public void edit(ScheduledJobPO scheduledJobPO) {
        if (CommonConstant.NORMAL.equals(scheduledJobPO.getJobStatus())) {
            schedulerDelete(scheduledJobPO.getId());
            schedulerAdd(scheduledJobPO.getId(), scheduledJobPO.getClassName().trim(), scheduledJobPO.getCronExpression().trim(), scheduledJobPO.getParams());
        } else {
            try {
                scheduler.pauseJob(JobKey.jobKey(scheduledJobPO.getId()));
            } catch (SchedulerException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
        }
        super.updateById(scheduledJobPO);
    }


    @Override
    public void delete(List<String> ids) {
        ids.forEach(this::schedulerDelete);
        super.removeBatchByIds(ids);
    }

    @Override
    public void execute(ScheduledJobPO scheduledJobPO) {
        try {
            String jobName = scheduledJobPO.getClassName().trim();
            Date startDate = new Date();
            String ymd = new SimpleDateFormat("yyyyMMddHHmmss").format(startDate);
            String identity = jobName + ymd;
            //0.1秒后执行 只执行一次
            startDate.setTime(startDate.getTime() + 100L);
            // 定义一个Trigger
            SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                    .withIdentity(identity, JOB_EXECUTE_GROUP)
                    .startAt(startDate)
                    .build();
            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(jobName).getClass()).withIdentity(identity).usingJobData("params", scheduledJobPO.getParams()).build();
            // 将trigger和 jobDetail 加入这个调度
            scheduler.scheduleJob(jobDetail, trigger);
            // 启动scheduler
            scheduler.start();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 添加定时任务
     *
     * @param id
     * @param className
     * @param cronExpression
     * @param params
     */
    private void schedulerAdd(String id, String className, String cronExpression, String params) {
        try {
            // 启动调度器
            scheduler.start();

            // 构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(className).getClass()).withIdentity(id).usingJobData("params", params).build();

            // 表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);

            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(id).withSchedule(scheduleBuilder).build();

            scheduler.scheduleJob(jobDetail, trigger);
        } catch (SchedulerException e) {
            throw new RuntimeException("创建定时任务失败", e);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param id
     */
    private void schedulerDelete(String id) {
        try {
            scheduler.pauseTrigger(TriggerKey.triggerKey(id));
            scheduler.unscheduleJob(TriggerKey.triggerKey(id));
            scheduler.deleteJob(JobKey.jobKey(id));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("删除定时任务失败");
        }
    }

    private static Job getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (Job) class1.newInstance();
    }

}
